#include <string>
#include <json/json.h>
#include <json/writer.h>
#include <iostream>
#include <fstream>
using namespace std;
 
void readFileJson(); //从文件中读取JSON，一个存储了JSON格式字符串的文件
int modify_param_json(const char * fileName,const char* pathInJson, Json::Value & condition, Json::Value & valueToSet);

int main(int argc, char *argv[]) 
{
    //readFileJson();
    
    Json::Value con;
    con["ele"] = "openlid_y";
    
    Json::Value valueToSet;
    valueToSet["acc"] = 8000;

    
    modify_param_json("test.json",".openlid.goto_open.electl",con,valueToSet);
    return 0;
}

typedef enum
{
    LIQUID_DP1_1,
    LIQUID_DP1_M,
    LIQUID_DJP_BIG_1,
    LIQUID_DJP_BIG_M,
    LIQUID_DJP_SMALL_1,
	LIQUID_DJP_SMALL_M,
    LIQUID_DJQ_1,
    LIQUID_DJQ_M,
    LIQUID_DP8_ADD,
    LIQUID_DP8_WASTE,
    LIQUID_DP8_1_1,
    LIQUID_DP8_1_M,
    MAX_NUM_LIQUID_CTL,
}en_liquid_ctl_type;

typedef enum
{
    COM_5UL,
    COM_6UL,
    COM_7UL,
    COM_8UL,
    COM_9UL,
    MAX_NUM_COM_VOLUME,
}en_compensate_volume;

typedef struct 
{
   int spitTimes;
   float * compensateHead;
}compensate_t;

typedef struct
{
    int numTimes;
    compensate_t * spitTimesTypeHead;
}compensate_v;


typedef struct _suck_param
{
   int posPre; // the previous position
   int speedPre; // the speed go to previous position
   float air1Quan; // the air quantity before suck liquid
   int speedDetect;// the speed of detecting liquid face
   int threshold; // the threshold of detecting
   int stepBelow;// the step continue to go after detecting success
   float speedSuck;// the suck speed
   float quantity; // the suck quantity
   float more; // the reduntant quantity
   int posMax; //the max pos to go if no liquid 
   int posPost; // the position after sucking finished 
   int speedPost; // the speed to go to posPost
   float air2Quan; // the air quantity after suck liquid    
   float spitQuan; // spit back quantity
   float speedSuckAir1;//ul/s
   int delayAfterSuck; //
   int delayAfterSpit; //
   float speedSuckAir2;//ul/s
   unsigned int spitSpeed;//inc/s
}suck_param,*pSuck_param;

typedef struct _tecan_liquid_param
{
   int posPre;
   int posPost;
   int posMax;
   float quantity; // the unit is uL
   float quanSpitAir1;
   float quanSuckBack;
   int speed;
   unsigned int  delayAfterSpit; // ms
   unsigned int  speedGoUp; // speed when go up back
   float   speedSuckBack;//speed suck back ul/s
}tecan_liquid_param, *pSpit_param;

class CLiquidCtl
{
public:
    static CLiquidCtl* get_instance(void);
    virtual ~CLiquidCtl();

private:
    static CLiquidCtl * m_pInstance;

    CLiquidCtl(){};
    CLiquidCtl(const CGpLayout & ){};
    CLiquidCtl & operator = (const CLiquidCtl & ){};
    CLiquidCtl(const char * fileIn);

    class CGarbo     
    {    
    public:    
        ~CGarbo()    
        {    
            if(CLiquidCtl::m_pInstance)    
                delete CLiquidCtl::m_pInstance; 

            std::cout<<"~CGarbo"<<std::endl;   
        }    
    };
        
    static CGarbo Garbo; 

    suck_param m_suckParamrArr[MAX_NUM_LIQUID_CTL];
    tecan_liquid_param m_spitParamArr[MAX_NUM_LIQUID_CTL];

    compensate_v dp1SpitCompensateArr[MAX_NUM_COM_VOLUME];

    void loadLiquidCtl(const char * filePathIn);
    
};


void load_dp1_liqiud_ctl(Json::Value & valueIn, suck_param *pSuckParamOut,
tecan_liquid_param*pSpitParamOut,compensate_v * dp1SpitCompensate);


 
//从文件中读取JSON
void CLiquidCtl::loadLiquidCtl(const char * filePathIn)
{
    Json::Reader reader;
    Json::Value root;
 
    //从文件中读取，保证当前文件有test.json文件
    ifstream in("liquid.json", ios::binary);
    //in.open("test.json", ios::binary);
 
    if( !in.is_open() )  
    { 
       cout << "Error opening file\n"; 
       return; 
    }
 
 
    if(reader.parse(in,root))
    {
    
	    Json::Value::Members listNameModule = root.getMemberNames();
            Json::Value::Members::iterator itModule = listNameModule.begin();

            while(itModule!=listNameModule.end())
            {

                if((*itModule).compare("dp1")==0)
                {
                     
                }
                else if((*itModule).compare("dj_qpcr")==0)
                {
                    
                }
                else if((*itModule).compare("dj_purify_big")==0) 
                {
                     
                }
                else if((*itModule).compare("dj_purify_small")==0) 
                {
                     
                }
                else if((*itModule).compare("dp8")==0) 
                {
                      
                }
                itModule++;
            }
	    
            reader.clear();
	    in.close();
    }
}


int modify_param_json(const char * fileName,const char* pathInJson, Json::Value & condition, Json::Value & valueToSet)
{
    Json::Reader reader;
    Json::Value root;
 
    //从文件中读取，保证当前文件有test.json文件
    std::ifstream in;//(configFiles_json[fileId], std::ios::binary);
    //in.open("test.json", ios::binary);
    //std::cout<<"enter in read_param_json"<<std::endl;
    in.open(fileName, std::ios::binary);
    if( !in.is_open() )  
    { 
        std::cout << "Error opening file\n"; 
        return -1; 
    }
    reader.parse(in,root); 
    
    if(root.empty())
    {
        std::cout << "Error parse json content\n"; 
        return -2;
    }
    
    
   // int count = 0;
    
    std::string path(pathInJson);

    Json::Path pathInfile(path); 
    cout<<"create jason path success"<<endl;

    Json::Value valueTar = pathInfile.resolve(root);


    std::string strPath(pathInJson);

    std::vector<std::string> strvec;
    strvec.clear();

    std::string::size_type pos1, pos2;
    pos2 = strPath.find('.');
    pos1 = 0;
    while (std::string::npos != pos2)
    {
        strvec.push_back(strPath.substr(pos1, pos2 - pos1));

        pos1 = pos2 + 1;
        pos2 = strPath.find('.', pos1);
    }
    strvec.push_back(strPath.substr(pos1));
    //Json::Value valueTar ;

    //printf("in read_param_json strvec.size:%d\n",strvec.size());
//    for(int istr = 0;istr<strvec.size();istr++)
//    {
//        if(istr==0)
//        {
//           valueTar = root[strvec[istr]];
//        }
//        else if(!valueTar.empty())
//        {
//           valueTar =  valueTar[strvec[istr]];
//        }
        //std::cout<<"keystr:"<<strvec[istr]<<std::endl;
        
//    }

    if(valueTar.empty())
    {
        cout<<"no value for path:"<<pathInJson<<endl;
    }

    std::string keyNameCon = condition.getMemberNames()[0];
    std::string keyNameSet = valueToSet.getMemberNames()[0];
    
    if(valueTar.isObject() && !valueTar.isArray())
    {
      //cout<<"key:"<<*itMem<<";value:"<<valueTar[*itMem].asString();
      std::vector<std::string> mem = valueTar.getMemberNames();

      std::vector<std::string>::iterator itMem = mem.begin();

      while(itMem!=mem.end())
      {
          cout<<"key:"<<*itMem<<";value:"<<valueTar[*itMem].asString();

          if(keyNameCon == *itMem && condition[keyNameCon] == valueTar[*itMem])
          {
             cout<<"the nod is found"<<endl;
          }

          itMem ++ ;
      }

      
          
    }
    else if(valueTar.isArray())
    {
      int sizeArray = valueTar.size();
      cout<<"sizeArray:"<<sizeArray<<endl;
      for(int i=0;i<sizeArray;i++)
      {
           std::vector<std::string> mem = valueTar[i].getMemberNames();

	   std::vector<std::string>::iterator itMem = mem.begin();

	   while(itMem!=mem.end())
	   {
		cout<<"key:"<<*itMem<<",type:"<<valueTar[i][*itMem].type();
                if(valueTar[i][*itMem].type() == Json::stringValue)
                {
                    cout<<";value:"<< valueTar[i][*itMem].asString()<<endl;
                }
                else
                {
                   cout<<";value:"<< valueTar[i][*itMem].asInt()<<endl;
                }
                if(keyNameCon == *itMem && condition[keyNameCon] == valueTar[i][*itMem])
                {
                   cout<<"the node is found"<<endl;
                   //valueTar[i][keyNameSet] = valueToSet[keyNameSet];
                   valueTar[i].clear();
                }
		itMem ++ ;
	   }
           cout<<"--------"<<endl<<endl;
           
      }
    }

    Json::StyledStreamWriter writer;
    ofstream outFile;
    outFile.open("test1.json");
    writer.write(outFile,root);

    root.clear();

    in.close();
    outFile.close();

    return 0;    
}


void readFileJson()
{
    Json::Reader reader;
    Json::Value root;
 
    //从文件中读取，保证当前文件有test.json文件
    ifstream in("test.json", ios::binary);
    //in.open("test.json", ios::binary);
 
    if( !in.is_open() )  
    { 
    cout << "Error opening file\n"; 
    return; 
    }
 
    if(reader.parse(in,root))
    {
	    Json::Value gotoOpen = root["openlid"]["goto_open"]["electl"];
	    int count = gotoOpen.size();
	    cout<<"num is "<<count<<endl;

	    for(int i=0;i<count;i++)
	    {
		Json::Value eleCtl = gotoOpen[i];
	
		cout<<"ele name:"<<eleCtl["ele"].asString();
		cout<<",position:"<<eleCtl["position"].asInt();
		cout<<",speed:"<<eleCtl["speed"].asInt();
		cout<<",acc:"<<eleCtl["acc"].asInt();
		cout<<",dec:"<<eleCtl["dec"].asInt()<<endl;       
	    }
	    
	    in.close();
    }
}

void load_suck_param(Json::Value & valueIn, suck_param *pSuckParamOut)
{
    Json::Value * valueTemp = &valueIn["air1Volume"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->air1Quan = valueTemp->asFloat();
    }

    valueTemp = &valueIn["speedSuck"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->speedSuck= valueTemp->asFloat();
    } 

    valueTemp = &valueIn["moreVolume"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->more = valueTemp->asFloat();
    } 

    valueTemp = &valueIn["air2Volume"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->air2Quan = valueTemp->asFloat();
    } 

    valueTemp = &valueIn["spitVolume"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->spitQuan = valueTemp->asFloat();
    } 

    valueTemp = &valueIn["speedSuckAir1"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->speedSuckAir1 = valueTemp->asFloat();
    } 

    valueTemp = &valueIn["delayAfterSuck"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->delayAfterSuck = valueTemp->asInt();
    }

    valueTemp = &valueIn["delayAfterSpit"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->delayAfterSpit = valueTemp->asInt();
    }

    valueTemp = &valueIn["speedSuckAir2"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->speedSuckAir2 = valueTemp->asFloat();
    }

    valueTemp = &valueIn["speedSpit"];
    if(!valueTemp->empty())
    {
        pSuckParamOut->spitSpeed = valueTemp->asInt();
    }

}

void load_spit_param(Json::Value & valueIn, tecan_liquid_param *pSpitParamOut)
{
    Json::Value * valueTemp = &valueIn["air1Volume"];
    if(!valueTemp->empty())
    {
        pSpitParamOut->quanSpitAir1 = valueTemp->asFloat();
    }

    valueTemp = &valueIn["suckBackVolume"];
    if(!valueTemp->empty())
    {
        pSpitParamOut->quanSuckBack = valueTemp->asFloat();
    } 

    valueTemp = &valueIn["spitSpeed"];
    if(!valueTemp->empty())
    {
        pSpitParamOut->speed = valueTemp->asFloat();
    } 

    valueTemp = &valueIn["delayAfterSpit"];
    if(!valueTemp->empty())
    {
        pSpitParamOut->delayAfterSpit = valueTemp->asInt();
    } 

    valueTemp = &valueIn["speedGoUp"];
    if(!valueTemp->empty())
    {
        pSpitParamOut->speedGoUp = valueTemp->asInt();
    } 

    valueTemp = &valueIn["speedSuckBack"];
    if(!valueTemp->empty())
    {
        pSpitParamOut->speedSuckBack = valueTemp->asFloat();
    } 

}


void load_dp1_liqiud_ctl(Json::Value & valueIn, suck_param *pSuckParamOut,
tecan_liquid_param*pSpitParamOut,compensate_v * dp1SpitCompensate)
{
	 Json::Value::Members listNameCtlType = valueIn.getMemberNames();
     Json::Value::Members::iterator itCtlType = listNameCtlType.begin(); 

     while(itCtlType!=listNameCtlType.end())
     {
         if((*itCtlType).compare("suck1")==0)
         {
             load_suck_param(valueIn["suck1"],pSuckParamOut+LIQUID_DP1_1);
         }
         else if((*itCtlType).compare("suckm")==0)
         {
             load_suck_param(valueIn["suckm"],pSuckParamOut+LIQUID_DP1_M);             
         }
         else if((*itCtlType).compare("spit1")==0)
         {
             load_spit_param(valueIn["spit1"],pSpitParamOut+LIQUID_DP1_1);
         }
         else if((*itCtlType).compare("spitm")==0)
         {
             load_spit_param(valueIn["spitm"],pSpitParamOut+LIQUID_DP1_M);          
         }
         
         itCtlType ++;
     }
}

